Video Thumbnail
4:28
4:14
clock icon Created with Sketch. 4 minutes

Solution: SQL to ORM

Although in the video I’m using Pydantic V1, we’ve updated the code example to Pydantic V2. As a result, there might be minor differences between the code you see in the video and the code in the Git repository. Notably, .dict() has been replaced by .model_dump().


Mathijs Peeters

Hi Arjan team,
So far I've been quite happy with the challenges, so I was surprised with this one.
I'd like to give some constructive feedback regarding my experience:

- Perhaps it's because I'm lacking experience with web developement and interacting with databases, but I found this challenge quite overwhelming. There were two factors that contributed to this:
1) first is that the provided resources are lacking in my opinion - the linked video only briefly shows sqlalchemy (it's only one third of the video and just explains the core idea of an ORM). I found myself watching a bunch of other youtube tutorials and ended up in tutorial hell (which is exactly what I want to avoid with this course).
2) The second factor is that I have the impression that sqlalchemy provides a bunch of different ways to access the same functionality, making it all rather confusing (for example one can create a Base class by inheriting from sqlalchemy.orm.DeclarativeBase or just use Base = sqlalchemy.ext.declarative.declarative_base() - same with select, mapped_column etc.).
On top of that, this challenge both adds FastAPI (which isn't too difficult here - but still adds complexity) and SQLAlchemy in one go.

I hope this feedback is helpful.
PS: One question I have is where I could find info on the dependency injection mechanism that FastAPI has that is used in the solution here ?

Best regards,
Mathijs

REPLY
Arjan Egges

Hi Mathijs, thanks for the feedback! We'll take it into account and see if we can update this challenge to provide a better starting point. This is the dependency injection mechanism that's built into FastAPI: https://fastapi.tiangolo.com/tutorial/dependencies.

REPLY
Manuel Escalona

Do you know why I am getting this error running your Fast API code?

" File "C:\Users\mescalona\arjancodes\30-day-design-challenge-21-30\22_sql_to_orm\after\models.py", line 4, in
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
ImportError: cannot import name 'DeclarativeBase' from 'sqlalchemy.orm' (C:\Users\mescalona\anaconda3\Lib\site-packages\sqlalchemy\orm\__init__.py) "

I tried to install SQLalchemy, but it was already installed:

" Requirement already satisfied: sqlalchemy in c:\users\mescalona\anaconda3\lib\site-packages (1.4.39)
Requirement already satisfied: greenlet!=0.4.17 in c:\users\mescalona\anaconda3\lib\site-packages (from sqlalchemy) (2.0.1)"

REPLY
Juan Diego Latorre Ramirez

I currently use Tortoise-ORM in my projects (combined with FastAPI). It is a good stack for creating asynchronous applications.

REPLY
Arjan Egges

Thanks for the suggestion!

REPLY
Hud Wahab

For some reason had to add response_model=None in every method e.g.
`@app.post("/events/", response_model=None)` for this to run. Not sure if that's intended

REPLY
Nico Neumann

Did you try to add type hints for the output?
You can read more about it here: https://fastapi.tiangolo.com/tutorial/response-model/#response_model-parameter

I defined it like this:
@app.post("/events", response_model=EventCreate)
async def create_event(event: EventCreate, database: Session = Depends(get_db)) -> Any:

REPLY
Arjan Egges

Good suggestion - I haven't added return type hints to the solution, but this might very well solve the issue.

REPLY
Michael Brittain

I don't understand the typing needed for the routing functions. For example, although the get_event function returns a models.Event, presumably the async nature means some kind of promise is actually returned?

Also, it seems the model.dict() method is deprecated in favour of model_dump().

REPLY
Arjan Egges

Hi Michael, an async function in Python will return a coroutine. However, as opposed to languages like Typescript, in Python you generally don't explicitly write the Coroutine return type. It's implicitly known from using the async keyword that the return type will be Coroutine. I do prefer the way it's handled in Typescript as it's clearer in my opinion.

I'll make a note of updating model.dict to model_dump when I update the challenge code - thanks for mentioning that!

REPLY